package com.hsj.core.factory;

import com.hsj.core.entity.Bean;
import com.hsj.core.entity.Property;
import com.hsj.core.utils.ParseXmlUtil;
import com.hsj.core.utils.StringUtil;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 获取bean对象的工厂
 * @author:Teacher黄
 * @date:Created at 2019/05/12
 */
public class BeanFactory {

    /**
     * 对应bean的容器
     * 解析xml创建出来的对象就装入这个容器
     */
    private static Map<String,Object> beanMap = new HashMap<>(16);

    private static List<Bean> beanList;

    static {
        // 加载xml
        beanList = ParseXmlUtil.parse("config.xml");
        // 实例化bean对象
        instanceBean();
        // 注入属性
        injectBean();
    }

    /**
     * 实例化xml中的对象
     */
    private static void instanceBean(){
        try {
            // 遍历bean
            for (Bean bean : beanList) {
                // 实例化对应的对象
                Object o = Class.forName(bean.getClassName()).getConstructor().newInstance();
                // 存入beanMap
                beanMap.put(bean.getName(),o);
            }
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
        }
    }


    /**
     * 给对应的bean对象注入属性
     */
    private static void injectBean(){
        try {
            // 遍历beanList
            for (Bean bean : beanList) {
                // 获取bean对象
                Object o = beanMap.get(bean.getName());
                // 对应的class对象
                Class clazz = o.getClass();
                // 遍历property
                List<Property> propertyList = bean.getPropertyList();
                for (Property property : propertyList) {
                    // 依次注入对应的属性
                    // 获取对应的属性对象
                    Field field = clazz.getDeclaredField(property.getName());
                    // 获取属性的数据类型
                    Class<?> type = field.getType();
                    // 组装setter方法
                    String methodName = StringUtil.mkSetter(property.getName());
                    // 获取方法对象
                    Method method = clazz.getDeclaredMethod(methodName, type);
                    // 动态调用
                    // 要区分是否由ref
                    if(property.getRef() == null){
                        // 没有关联对象
                        method.invoke(o,type.getConstructor(String.class).newInstance(property.getValue()));
                    }else{
                        // 关联了对象
                        method.invoke(o,beanMap.get(property.getRef()));
                    }
                }
            }
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } finally {
        }
    }

    /**
     * 获取bean对象
     * @param name : 对应bean的名字
     * @return
     */
    public static Object getBean(String name){
        return beanMap.get(name);
    }

}
